package com.xidian.zhiancloud.util.tools;

import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 日期处理
 *
 * @author lill
 */
public class DateUtils {

    protected static Logger logger = LoggerFactory.getLogger(DateUtils.class);
    /**
     * 时间格式(yyyy-MM-dd)
     */
    public static final String DATE_PATTERN = "yyyy-MM-dd";
    /**
     * 无分隔符日期格式 "yyyyMMddHHmmssSSS"
     */
    public static final String DATE_TIME_PATTERN_YYYY_MM_DD_HH_MM_SS_SSS = "yyyyMMddHHmmssSSS";

    public static final String DATE_TIME_PATTERN_YYYY_MM_DD_HH_MM_SS = "yyyyMMddHHmmss";
    /**
     * 时间格式(yyyy-MM-dd HH:mm:ss)
     */
    public static final String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";

    /**
     * 时间格式(yyyy年MM月dd日)
     */
    public final static String DATE_TIME_TXT = "yyyy年MM月dd日";

    /**
     * 日期转换格式数组
     */
    public static String[][] regularExp = new String[][]{

            // 默认格式
            {"\\d{4}-((([0][1,3-9]|[1][0-2]|[1-9])-([0-2]\\d|[3][0,1]|[1-9]))|((02|2)-(([1-9])|[0-2]\\d)))\\s+([0,1]\\d|[2][0-3]|\\d):([0-5]\\d|\\d):([0-5]\\d|\\d)",
                    DATE_TIME_PATTERN},
            // 仅日期格式 年月日
            {"\\d{4}-((([0][1,3-9]|[1][0-2]|[1-9])-([0-2]\\d|[3][0,1]|[1-9]))|((02|2)-(([1-9])|[0-2]\\d)))",
                    DATE_PATTERN},
            //  带毫秒格式
            {"\\d{4}((([0][1,3-9]|[1][0-2]|[1-9])([0-2]\\d|[3][0,1]|[1-9]))|((02|2)(([1-9])|[0-2]\\d)))([0,1]\\d|[2][0-3])([0-5]\\d|\\d)([0-5]\\d|\\d)\\d{1,3}",
                    DATE_TIME_PATTERN_YYYY_MM_DD_HH_MM_SS_SSS}
    };

    public static String format(Date date) {
        return format(date, DATE_PATTERN);
    }

    public static String format(Date date, String pattern) {
        if (date != null) {
            SimpleDateFormat df = new SimpleDateFormat(pattern);
            return df.format(date);
        }
        return null;
    }

    public static String timeToStr(Long time, String pattern) {
        SimpleDateFormat dateFormat = new SimpleDateFormat(pattern);
        if (time.toString().length() < 13) {
            time = time * 1000L;
        }
        Date date = new Date(time);
        String value = dateFormat.format(date);
        return value;
    }

    public static long strToTime(String timeStr) {
        Date time = strToDate(timeStr);
        return time.getTime() / 1000;
    }


    /**
     * 转换为时间类型格式
     *
     * @param strDate 日期
     * @return
     */
    public static Date strToDate(String strDate) {
        try {
            String strType = getDateFormat(strDate);
            SimpleDateFormat sf = new SimpleDateFormat(strType);
            return new Date((sf.parse(strDate).getTime()));
        } catch (Exception e) {
            return null;
        }
    }


    /**
     * 根据传入的日期格式字符串，获取日期的格式
     *
     * @return 秒
     */
    public static String getDateFormat(String date_str) {
        String style = null;
        if (!StringUtils.isNotEmpty(date_str)) {
            return null;
        }
        boolean b = false;
        for (int i = 0; i < regularExp.length; i++) {
            b = date_str.matches(regularExp[i][0]);
            if (b) {
                style = regularExp[i][1];
            }
        }
        if (StringUtils.isEmpty(style)) {
            logger.info("date_str:" + date_str);
            logger.info("日期格式获取出错，未识别的日期格式");
        }
        return style;
    }

    /**
     * 将字符串类型的转换成Date类型
     *
     * @param dateStr 字符串类型的日期 yyyy-MM-dd
     * @return Date类型的日期
     * @throws ParseException
     */
    public static Date convertStringToDate(String dateStr) {
        // 返回的日期
        Date resultDate = null;
        try {
            // 日期格式转换
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            resultDate = sdf.parse(dateStr);
        } catch (ParseException e) {
        }
        return resultDate;
    }
    /**
     * 将长时间格式字符串转换为时间 yyyy-MM-dd HH:mm:ss
     *
     * @param strDate
     * @return
     */
    public static Date strToDateLong(String strDate) {
        SimpleDateFormat formatter = new SimpleDateFormat(DATE_TIME_PATTERN);
        ParsePosition pos = new ParsePosition(0);
        Date strtodate = formatter.parse(strDate, pos);
        return strtodate;
    }

    /**
     * 将字符串类型的转换成Date类型
     *
     * @param dateStr 字符串类型的日期 yyyy-MM-dd
     * @return Date类型的日期
     * @throws ParseException
     */
    public static Date convertStringToDate(String dateStr,String format) {
        // 返回的日期
        Date resultDate = null;
        try {
            // 日期格式转换
            SimpleDateFormat sdf = new SimpleDateFormat(format);
            resultDate = sdf.parse(dateStr);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return resultDate;
    }


    /**
     * 日期顺延number个年
     */
    public static Date getAfterYear(Date date,int number) {
        Calendar c = Calendar.getInstance();//获得一个日历的实例
        if(date==null){
            date =new Date();
        }
        c.setTime(date);//设置日历时间
        c.add(Calendar.YEAR,number);//在日历的月份上增加n个月
        return c.getTime();
    }

    /**
     * 日期顺延number个月
     */
    public static Date getAfterMonth(Date date,int number) {
        Calendar c = Calendar.getInstance();//获得一个日历的实例
        if(date==null){
            date =new Date();
        }
        c.setTime(date);//设置日历时间
        c.add(Calendar.MONTH,number);//在日历的月份上增加n个月
        return c.getTime();
    }
    /**
     * 日期顺延number个天
     */
    public static Date getAfterDay(Date date,int number) {
        Calendar c = Calendar.getInstance();//获得一个日历的实例
        if(date==null){
            date =new Date();
        }
        c.setTime(date);//设置日历时间
        c.add(Calendar.DAY_OF_MONTH,number);//在日历的月份上增加n个月
        return c.getTime();
    }

    /**
     * 两个日期的之间的绝对值
     * @param date1
     * @param date2
     * @return
     * @throws ParseException
     */
    public static int getMonthSpace(String date1, String date2)
            throws ParseException {
        int result = 0;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Calendar c1 = Calendar.getInstance();
        Calendar c2 = Calendar.getInstance();
        c1.setTime(sdf.parse(date1));
        c2.setTime(sdf.parse(date2));
        result = c2.get(Calendar.MONTH) - c1.get(Calendar.MONTH);

        return result == 0 ? 1 : Math.abs(result);

    }

    /**
     * 获取两个时间之间的天数绝对值
     * @param date1
     * @param date2
     * @return
     * @throws ParseException
     */
    public static long getDaySpace(String date1, String date2)
            throws ParseException {
//        int result = 0;
        String[] startStr = new SimpleDateFormat("yyyy-MM-dd").format(convertStringToDate(date1)).split("-");
        String[] endStr = new SimpleDateFormat("yyyy-MM-dd").format(convertStringToDate(date2)).split("-");
        Integer startYear = Integer.parseInt(startStr[0]);
        Integer startMonth = Integer.parseInt(startStr[1]);
        Integer startDay = Integer.parseInt(startStr[2]);
        Integer endYear = Integer.parseInt(endStr[0]);
        Integer endMonth = Integer.parseInt(endStr[1]);
        Integer endDay = Integer.parseInt(endStr[2]);
        LocalDate endLocalDate = LocalDate.of(endYear,endMonth,endDay);
        LocalDate startLocalDate = LocalDate.of(startYear,startMonth,startDay);

        return startLocalDate.until(endLocalDate,ChronoUnit.DAYS) + 1;

    }
    /**
     *根据时间范围获得月份集
     * @return
     */
    public static List<String> getRangeSet(String beginDate, String endDate){
        /*      Date1.after(Date2),当Date1大于Date2时，返回TRUE，当小于等于时，返回false；
          Date1.before(Date2)，当Date1小于Date2时，返回TRUE，当大于等于时，返回false；
          如果业务数据存在相等的时候，而且相等时也需要做相应的业务判断或处理时，你需要使用：！Date1.after(Date2);*/
        if ("".equals(beginDate)){
            beginDate = format(getAfterMonth(strToDate(endDate),-11),DATE_TIME_PATTERN);
        }
        List<String> rangeSet =null;
        SimpleDateFormat sdf = null;
        Date begin_date = null;
        Date end_date = null;
        rangeSet = new java.util.ArrayList<String>();
        sdf = new SimpleDateFormat("yyyy-MM");
        try {
            begin_date = sdf.parse(beginDate);//定义起始日期
            end_date = sdf.parse(endDate);//定义结束日期
        } catch (ParseException e) {
        }
        Calendar dd = Calendar.getInstance();//定义日期实例
        dd.setTime(begin_date);//设置日期起始时间
        while(!dd.getTime().after(end_date)){//判断是否到结束日期
            rangeSet.add(sdf.format(dd.getTime()));
            dd.add(Calendar.MONTH, 1);//进行当前日期月份加1
        }
        return rangeSet;
    }

    /**
     * 通过月来获取 这个月的起始时间和结束时间
     * @param yearMonth
     */
    public static List<String> getThisMonthDate(String yearMonth){
        Calendar c=Calendar.getInstance(Locale.CHINA);
        int year = Integer.parseInt(yearMonth.split("-")[0]);
        int month = Integer.parseInt(yearMonth.split("-")[1]);
        c.set(year,month,0);
        List<String> list = new ArrayList<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        int lastMonthMaxDay=c.getActualMaximum(Calendar.DAY_OF_MONTH);
        c.set(c.get(Calendar.YEAR), c.get(Calendar.MONTH), lastMonthMaxDay, 23, 59, 59);
        String gtime = sdf.format(c.getTime()); //最后一天
        SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-01 00:00:00");
        String gtime2 = sdf2.format(c.getTime());
        list.add(gtime2);
        list.add(gtime);
        return list;
    }

    /**
     * 通过某天时间获取 这一天得结束时间
     * @param dayTime
     */
    public static String getDayEndTime(Date dayTime){
        Calendar calendar = Calendar.getInstance();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DateUtils.DATE_TIME_PATTERN);
        calendar.setTime(dayTime);
        calendar.set(Calendar.HOUR_OF_DAY,23);
        calendar.set(Calendar.MINUTE,59);
        calendar.set(Calendar.SECOND,59);
        calendar.set(Calendar.MILLISECOND,999);
        Date dayEnd = calendar.getTime();
        String endStr = simpleDateFormat.format(dayEnd);
        return endStr;
    }
    /**
     * 通过某天时间获取 这一天得开始时间
     * @param dayTime
     */
    public static String getDayBeginime(Date dayTime){
        Calendar calendar = Calendar.getInstance();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DateUtils.DATE_TIME_PATTERN);
        calendar.setTime(dayTime);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        Date dayBegin = calendar.getTime();
        String beginStr = simpleDateFormat.format(dayBegin);
        return beginStr;
    }


    /**
     * 获取同比环比返回时间
     * @param param
     * @return
     */
    public static Map<String,Object> getTongBiHuanBiDate(Map<String,Object> param){
        SimpleDateFormat dateFormat = new SimpleDateFormat(DateUtils.DATE_TIME_PATTERN);
        String beginDateStr = param.get("beginDate") + "";
        String endDateStr = param.get("endDate") + "";
        Date beginDate = DateUtils.strToDate(beginDateStr);
        Date endDate = DateUtils.strToDate(endDateStr);
        Object type = param.get("type");
        // 同比开始日期
        String yearOnYearBeginDate = "";
        // 同比结束日期
        String yearOnYearEndDate = "";
        // 环比开始日期
        String ringRatioBeginDate = "";
        // 环比结束日期
        String ringRatioEndDate = "";
        // 天  天  和上个月的今天 ;  天  和昨天
        if ("day".equals(type)) {
            yearOnYearBeginDate = dateFormat.format(DateUtils.getAfterMonth(beginDate, -1));
            yearOnYearEndDate = dateFormat.format(DateUtils.getAfterMonth(endDate, -1));
            ringRatioBeginDate = dateFormat.format(DateUtils.getAfterDay(beginDate, -1));
            ringRatioEndDate = dateFormat.format(DateUtils.getAfterDay(endDate, -1));
        }
        // 周  周   和上个月的这周  ； 周   和上一周
        if ("week".equals(type)) {
            yearOnYearBeginDate = dateFormat.format(DateUtils.getAfterMonth(beginDate, -1));
            yearOnYearEndDate = dateFormat.format(DateUtils.getAfterMonth(endDate, -1));
            ringRatioBeginDate = dateFormat.format(DateUtils.getAfterDay(beginDate, -7));
            ringRatioEndDate = dateFormat.format(DateUtils.getAfterDay(endDate, -7));
        }
        // 月   月   和去年的这个月 ；  月   和上个月
        if ("month".equals(type)) {
            yearOnYearBeginDate = dateFormat.format(DateUtils.getAfterMonth(beginDate, -12));
            yearOnYearEndDate = dateFormat.format(DateUtils.getAfterMonth(endDate, -12));
            ringRatioBeginDate = dateFormat.format(DateUtils.getAfterMonth(beginDate, -1));
            ringRatioEndDate = dateFormat.format(DateUtils.getAfterMonth(endDate, -1));
        }
        // 年  年  和去年  ；  年  和去年
        if ("year".equals(type)) {
            yearOnYearBeginDate = dateFormat.format(DateUtils.getAfterMonth(beginDate, -12));
            yearOnYearEndDate = dateFormat.format(DateUtils.getAfterMonth(endDate, -12));
            ringRatioBeginDate = dateFormat.format(DateUtils.getAfterMonth(beginDate, -12));
            ringRatioEndDate = dateFormat.format(DateUtils.getAfterMonth(endDate, -12));
        }
        //近七天
        if("inSevenDays".equals(type)){
            yearOnYearEndDate = dateFormat.format(DateUtils.getAfterMonth(endDate, -1));
            yearOnYearBeginDate = getDayBeginime(DateUtils.getAfterDay(DateUtils.getAfterMonth(endDate, -1),-6));
            ringRatioEndDate = dateFormat.format(DateUtils.getAfterDay(endDate, -7));
            ringRatioBeginDate = getDayBeginime(DateUtils.getAfterDay((DateUtils.getAfterDay(endDate, -7)),-6));
        }
        //近三十天
        if("nearlyThirtyDays".equals(type)){
            yearOnYearEndDate = dateFormat.format(DateUtils.getAfterYear(endDate, -1));
            yearOnYearBeginDate = getDayBeginime(DateUtils.getAfterDay(DateUtils.getAfterYear(endDate, -1),-29));
            ringRatioEndDate = dateFormat.format(DateUtils.getAfterDay(endDate, -30));
            ringRatioBeginDate = getDayBeginime(DateUtils.getAfterDay(endDate, -59));
        }
        param.put("yearOnYearBeginDate", yearOnYearBeginDate);
        param.put("yearOnYearEndDate", yearOnYearEndDate);
        param.put("ringRatioBeginDate", ringRatioBeginDate);
        param.put("ringRatioEndDate", ringRatioEndDate);
        return param;
    }
    /**
     * date2比date1多的天数
     * @param date1
     * @param date2
     * @return
     */
    public static int differentDays(Date date1,Date date2) {
        Calendar cal1 = Calendar.getInstance();
        cal1.setTime(date1);

        Calendar cal2 = Calendar.getInstance();
        cal2.setTime(date2);
        int day1= cal1.get(Calendar.DAY_OF_YEAR);
        int day2 = cal2.get(Calendar.DAY_OF_YEAR);

        int year1 = cal1.get(Calendar.YEAR);
        int year2 = cal2.get(Calendar.YEAR);
        if(year1 != year2){
            //不同一年
            int timeDistance = 0 ;
            for(int i = year1 ; i < year2 ; i ++){
                if(i%4==0 && i%100!=0 || i%400==0) {
                    //闰年
                    timeDistance += 366;
                }else {
                    //不是闰年
                    timeDistance += 365;
                }
            }
            return timeDistance + (day2-day1) ;
        }else {
            //同一年
            return day2-day1;
        }
    }
    /**
     * 设置微信二维码失效时间，并返回具体失效的时间点
     * @param expire 二维码的有效时间，单位是毫秒
     * @param pattern 时间格式
     * @return
     */
    public static String getExpireTime(Date now, Long expire, String pattern) {
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        Date afterDate = new Date(now .getTime() + expire);
        return sdf.format(afterDate );
    }

    public static long getExpireTime(Date now, Date date, String dateType) {
        long l = now.getTime() - date.getTime();
        long day = l/(24*60*60*1000);
        if("D".equals(dateType)){
            return day;
        }
        long hour = (l/(60*60*1000));
        if("H".equals(dateType)){
            return hour;
        }
        long min = ((l/(60*1000)));
        if("M".equals(dateType)){
            return min;
        }
        long s = (l/1000);
        if("S".equals(dateType)){
            return s;
        }
        return l;
    }

//    public static void main(String[] args) {
//        try{
////            long daySpace = getDaySpace("2019-01-01 00:00:00", "2019-12-31 23:59:59");
////            List<String> daySpace = getRangeSet("2018-10-01 00:00:00", "2019-10-31 23:59:59");
//            SimpleDateFormat dateFormat = new SimpleDateFormat(DateUtils.DATE_TIME_PATTERN);
//            Map<String,Object> map = new HashedMap();
//            map.put("endDate","2019-12-04 23:59:59");
//            map.put("beginDate","2019-11-28 00:00:00");
//            map.put("type","inSevenDays");
//            Map<String,Object> map1 = getTongBiHuanBiDate(map);
//            System.err.println("getTongBiHuanBiDate:"+map1);
//            Date date = dateFormat.parse("2019-04-30 00:00:00");
//            String dayEndTime = getDayEndTime(date);
//            System.err.println("dayEndTime:"+dayEndTime);
//
//            Date da = getAfterMonth(date,-2);
//            System.err.println(dateFormat.format(da));
//
//
//        }catch (Exception e){
//
//        }
//    }



}
